const log4js = require('log4js');
const path = require('path');
const db = require('better-sqlite3')('data.db', { verbose: console.log });
// const puppeteer = require('puppeteer');
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());

log4js.configure({
    appenders: {
        dataFileOut: {
            type: "dateFile",
            filename: "./logs/log",
            pattern: "yyyy-MM-dd",
            alwaysIncludePattern: true,
        }
    },
    categories: {
        default: { appenders: ["dataFileOut"], level: "debug" }
    }
});
let logger = log4js.getLogger();
let browser;
let common = {
    apiUrl: 'http://ec.iqunkong.cn',
    username: 'manage',
    code: '618923',
    logger: logger
};

common.getUserName = function () {
    return common.getConfig('userName', 'manage');
}

common.getCode = function () {
    return common.getConfig('code', '618923');
}

//初始化数据库
common.initDb = function () {
    let configSql = 'CREATE TABLE "config" ("name" TEXT, "value" TEXT);';
    let configTable = db.prepare('select * from sqlite_master where type=? and name=?').get('table', 'config');

    if (!configTable) {
        db.prepare(configSql).run();
    }
}

//获取配置
common.getConfig = function (key, defaultValue) {
    let value = defaultValue;
    let settingRow = db.prepare('select * from config where name=?').get(key);

    if (!settingRow) {
        db.prepare('insert into config(name,value) values (?,?)').run(key, defaultValue);
        value = defaultValue;
    } else {
        value = settingRow.value;
    }

    return value;
}

//设置配置
common.setConfig = function (key, value) {
    let settingRow = db.prepare('select * from config where name=?').get(key);

    if (!settingRow) {
        db.prepare('insert into config(name,value) values (?,?)').run(key, value);
    } else {
        db.prepare('update config set value=? where name=?').run(value, key);
    }
}

//获取配置
common.getConfigs = function () {
    let configs = db.prepare("select * from config").all();
    return configs;
}

//随机数
common.randomNum = function (start, end) {
    return Math.floor(Math.random() * (end - start) + start)
}

//获取数字
common.getNumber = function (txt) {
    var result = 0;
    var regex = /\d+/;
    var matchResult = txt.match(regex);

    if (matchResult && matchResult.length > 0) {
        result = parseInt(matchResult[0]);
    }

    return result;
}

//获取url中的参数值
common.getUrlParam = function (url, parameter) {
    parameter = parameter.replace(/[\[\]]/g, '\\$&');
    let regex = new RegExp('[?&]' + parameter + '(=([^&#]*)|&|#|$)');
    let results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

//休眠
common.sleep = function (ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
}

common.padNumber = function (num) {
    return num.toString().padStart(2, '0');
}

//关闭浏览器
common.closeBrowser = async function () {
    if (browser) {
        await browser.close();
        browser = undefined;
    }
}

//获取浏览器
common.getBrowser = async function (isForceNew, proxy) {
    isForceNew = isForceNew || false;
    let args = ['--start-maximized', '--no-sandbox', '--disable-setuid-sandbox'];

    if (proxy) {
        args.push('--proxy-server=' + proxy);
    }

    if (browser && !browser.isConnected()) {
        await browser.close();
        browser = undefined;
    }

    if (isForceNew && browser) {
        await browser.close();
        browser = undefined;
    }

    if (!browser) {
        let executablePath = common.getConfig('exePath', '');

        if (!executablePath) {
            executablePath = path.join(process.cwd(), '.cache', 'puppeteer', 'chrome', 'win64-1095492', 'chrome-win', 'chrome.exe');
        }

        common.logger.warn(JSON.stringify(args));

        browser = await puppeteer.launch({
            headless: false,
            executablePath: executablePath,
            // executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
            ignoreDefaultArgs: ['--enable-automation'],
            args: args
        });
    }

    return browser;
}

//根据XPath点击节点
common.clickNodesByXPath = async function (xPath, page, timeout, delay) {
    timeout = timeout || 2000;
    delay = delay || 1500;
    let nodes = await page.$x(xPath);
    let endTime = new Date().getTime() + timeout;

    while (nodes.length < 1 && new Date().getTime() < endTime) {
        nodes = await page.$x(xPath);
        await common.sleep(400);
    }

    if (nodes.length > 0) {
        common.logger.warn('点击xpath ' + xPath);
        // await nodes[0].click();
        await nodes[0].evaluate(b => b.click());
        await common.sleep(delay);
    }
}

//等待节点消失
common.waitForNodeDisappear = function (page, xPath, timeout) {
    timeout = timeout || 0;
    return new Promise(async (resolve, reject) => {
        let endTime = new Date().getTime() + timeout;
        let nodes = await page.$x(xPath);

        while (nodes.length > 0 && new Date().getTime() <= endTime) {
            nodes = await page.$x(xPath);
            await common.sleep(500);
        }

        nodes = await page.$x(xPath);
        resolve(nodes.length);
    });
}

//清除文字内容
common.clearText = async function (selector, page) {
    let node = await page.$(selector);

    if (node) {
        await node.click({ clickCount: 3 });
        await common.sleep(200);
        await node.press('Backspace');
        await common.sleep(200);
    }
}

//根据缩放比例获取真实box
common.getBoxByScale = function (box) {
    if (common.scaleFactor != 1) {
        box.x = parseInt(box.x * common.scaleFactor);
        box.y = parseInt(box.y * common.scaleFactor);
        box.width = parseInt(box.width * common.scaleFactor);
        box.height = parseInt(box.height * common.scaleFactor);
    }

    return box;
}

//设置cookies
common.setCookies = async function (account, page) {
    let accountCookies = [];

    if (account.cookies && account.cookies.indexOf('{') > -1) {
        accountCookies = JSON.parse(account.cookies);
    }

    for (let index = 0; index < accountCookies.length; index++) {
        let cookie = accountCookies[index];
        await page.setCookie(cookie);
    }

    if (accountCookies.length < 1) {
        let deleteCookies = [{ "name": "l", "domain": ".taobao.com" }, { "name": "cna", "domain": ".taobao.com" }, { "name": "uc1", "domain": ".taobao.com" }, { "name": "tfstk", "domain": ".taobao.com" }, { "name": "csg", "domain": ".taobao.com" }, { "name": "sgcookie", "domain": ".taobao.com" }, { "name": "skt", "domain": ".taobao.com" }, { "name": "cookie2", "domain": ".taobao.com" }, { "name": "t", "domain": ".taobao.com" }, { "name": "isg", "domain": ".taobao.com" }, { "name": "_cc_", "domain": ".taobao.com" }, { "name": "sn", "domain": ".taobao.com" }, { "name": "xlly_s", "domain": ".taobao.com" }, { "name": "_tb_token_", "domain": ".taobao.com" }, { "name": "cancelledSubSites", "domain": ".taobao.com" }, { "name": "_m_h5_tk_enc", "domain": ".taobao.com" }, { "name": "_m_h5_tk", "domain": ".taobao.com" }, { "name": "unb", "domain": ".taobao.com" }, { "name": "_samesite_flag_", "domain": ".taobao.com" }];

        for (let index = 0; index < deleteCookies.length; index++) {
            await page.deleteCookie(deleteCookies[index]);
        }
    }

    await common.sleep(500);
}

module.exports = common;